#ifndef __WIZ_DATATYPE_WEAKPTR_HPP__SHANHAOBO_19800429__
#define __WIZ_DATATYPE_WEAKPTR_HPP__SHANHAOBO_19800429__

#include "./WizDataTypeSharedCounter.hpp"
#include "./WizDataTypeSharedPtr.hpp"

namespace Wiz
{
    namespace WeakPtr
    {

        template<class T>
        class Type
        {
        private:
            WIZ_DECLARE_CLASS_THIS(Type);
            typedef T                                   tElement;
            typedef ::Wiz::SharedPtr::Type<tElement>    TheSharedPtr;
        public:
            Type(): m_ManagedPtr(WIZ_NULLPTR), m_SharedCounter()
            {
            }

            template<class Y>
            Type(Type<Y> const & Other) : m_SharedCounter(Other.m_SharedCounter)
            {
                m_ManagedPtr = Other.Lock().Get();
            }

            template<class Y>
            Type(::Wiz::SharedPtr::Type<Y> const & Other) : m_ManagedPtr(Other.m_ManagedPtr), m_SharedCounter(Other.m_SharedCounter)
            {
            }

            template<class Y>
            Type& operator=(Type<Y> const & Other)
            {
                m_ManagedPtr    = Other.Lock().Get();
                m_SharedCounter = Other.m_SharedCounter;
                return *this;
            }

            template<class Y>
            Type& operator=(::Wiz::SharedPtr::Type<Y> const & Other) 
            {
                m_ManagedPtr    = Other.m_ManagedPtr;
                m_SharedCounter = Other.m_SharedCounter;
                return *this;
            }

            TheSharedPtr Lock() const 
            {
                if(Expired())
                {
                    return TheSharedPtr();
                }

                try
                {
                    return TheSharedPtr(*this);
                }
                catch(::Wiz::BadWeakPtr const &)
                {
                    return TheSharedPtr();
                }
            }

            ::Wiz::Bool::Type Expired() const
            {
                return m_SharedCounter.SharedCount() == 0;
            }

            ::Wiz::UInt::Type SharedCount() const
            {
                return m_SharedCounter.SharedCount();
            }

            ::Wiz::Void::Type Reset()
            {
                tThis().Swap(*this);
            }

            ::Wiz::Void::Type Swap(tThis & Other)
            {
                ::Wiz::Swap(m_ManagedPtr, Other.m_ManagedPtr);
                m_SharedCounter.Swap(Other.m_SharedCounter);
            }

            ::Wiz::Void::Type Set(T * px2, ::Wiz::SharedCounter::In pn2)
            {
                m_ManagedPtr = px2;
                m_SharedCounter = pn2;
            }

            template<class Y>
            ::Wiz::Bool::Type Less(Type<Y> const & rhs) const
            {
                return m_SharedCounter < rhs.m_SharedCounter;
            }

            T* m_ManagedPtr;
            ::Wiz::SharedCounter::Type m_SharedCounter;
        };  // Type
    } /// end of namespace WeakPtr

    template<class T, class U>
    WIZ_INLINE ::Wiz::Bool::Type operator<(::Wiz::WeakPtr::Type<T> const & A, ::Wiz::WeakPtr::Type<U> const & B)
    {
        return A.Less(B);
    }

    template<class T>
    WIZ_INLINE ::Wiz::Void::Type Swap(::Wiz::WeakPtr::Type<T>& A, ::Wiz::WeakPtr::Type<T>& B)
    {
        A.Swap(B);
    }
} /// end of namespace Wiz

//////////////////////////////////////////////////////////////////////////
#   define WIZ_DECLARE_WEAKPTR(t)                       \
    typedef ::Wiz:WeakPtr<t>            WeakPtr;        \
    typedef const ::Wiz::WeakPtr::Type<t>&    InWeakPtr;      \
    typedef ::Wiz::WeakPtr::Type<t>&          OutWeakPtr;     \
    typedef ::Wiz::WeakPtr::Type<t>&          InOutWeakPtr;
//////////////////////////////////////////////////////////////////////////

#endif /*__WIZ_DATATYPE_WEAKPTR_HPP__SHANHAOBO_19800429__*/
